﻿#include "EditorFolderAbilityView.h"
#include "EditorFolderAbilityViewModel.h"

#include "Widgets/RectangleWidget.h"
#include "Widgets/ImageWidget.h"
#include "Widgets/TextWidget.h"
#include "Widgets/Positioners/HorizontalPositionerWidget.h"
#include "Widgets/Positioners/VerticalPositionerWidget.h"
#include "Widgets/Mouse/MouseWidget.h"
#include "Widgets/EditorImageButton.h"
#include "Widgets/EditableText/EditorEditableTextView.h"
#include "Widgets/EditableText/EditorEditableTextViewModel.h"
#include "Widgets/Keyboard/KeyboardWidget.h"

#include "Framework/Editor.h"
#include "Theme/EditorTheme.h"



void REditorFolderAbilityView::CreateWidget(TSharedObjectPtr<RWidget> InParent)
{
    //create a widget that used when the list is empty
    auto EmptyWidget=NewWidget<RTextWidget>(InParent);
    EmptyWidget->Anchor.Fill(InParent);
    EmptyWidget->Text=U"未设置任何文件夹";
    EmptyWidget->Visible=[this](){return ViewModel->GetVisibleNodeNum()==0;};

    //to capture the shortcut key
    //such as delete key to delete the file
    //F2 to rename the file
    auto BackgroundKeyBoard=NewWidget<RKeyboardWidget>(InParent);
    BackgroundKeyBoard->Anchor.Fill(InParent);
    BackgroundKeyBoard->OnKeyboardInput.Bind([this](const SKeyboardEvent& InEvent)
    {
        if(InEvent.KeyState!=EKeyState::Pressed)
        {
            return false;
        }

        switch(InEvent.Key)
        {
            case EKey::Delete:
            {
                ViewModel->RemoveFocusedFileOrFolder();
                return true;
            }
            case EKey::F2:
            {
                ViewModel->RenameFocusedFileOrFolder();
                return true;
            }
        }
        return false;
    });
    RKeyboardWidgetWeakPtr WeakBackgroundKeyBoard=BackgroundKeyBoard;

    //空白区域控件，用于在列表长度不足时填充空白，实现在空白处也能触发鼠标事件
    {
        auto EmptyArea=NewWidget<RMouseWidget>(InParent);
        EmptyArea->Anchor.Fill(InParent);
        EmptyArea->OnClicked.BindLambda([this](const SMouseButtonEvent& InEvent)
        {
            if(InEvent.GetButton()!=EMouseButton::Right)
            {
                ViewModel->OnNodeClicked(-1);
            }
            else
            {
                ViewModel->OnNodeRightMouseButtonClicked(-1);
            }
            return true;
        });
    }

    //create a grey rectangle that highlight the hovered node
    auto HorverBackground=NewWidget<RRectangleWidget>(InParent);
    HorverBackground->Height=ViewModel->LineHeight;
    HorverBackground->Anchor.HorizontalFill(InParent);
    HorverBackground->FillColor=REditor::Get()->CurrentTheme->ItemHoverColor;
    HorverBackground->Visible=[this](){
        return ViewModel->GetHoveredNodeIndex()!=-1
        && ViewModel->GetFocusedNodeIndex()!=ViewModel->GetHoveredNodeIndex();
    };


    //高亮聚焦的文件/文件夹，鼠标右键不影响聚焦
    auto FocusedFileOrFolderHighlight=NewWidget<RRectangleWidget>(InParent);
    {
        FocusedFileOrFolderHighlight->Height=ViewModel->LineHeight;
        FocusedFileOrFolderHighlight->Anchor.HorizontalFill(InParent);
        FocusedFileOrFolderHighlight->FillColor=
            [this,WeakBackgroundKeyBoard](){
                if(WeakBackgroundKeyBoard->IsFocused())
                {
                    return REditor::Get()->CurrentTheme->ItemFocusSelectedColor;
                }
                return REditor::Get()->CurrentTheme->ItemSelectColor;
            };
        FocusedFileOrFolderHighlight->Visible=[this](){
            return ViewModel->GetFocusedNodeIndex()!=-1;
        };
    }

    //高亮刚刚点击的文件/文件夹，包括鼠标右键点击
    auto JustClickedFileOrFolderHighlight=NewWidget<RRectangleWidget>(InParent);
    {
        JustClickedFileOrFolderHighlight->Height=ViewModel->LineHeight;
        JustClickedFileOrFolderHighlight->Anchor.HorizontalFill(InParent);
        JustClickedFileOrFolderHighlight->Fill=false;
        JustClickedFileOrFolderHighlight->BorderSize=[this,WeakBackgroundKeyBoard]() ->float
        {
            if(!WeakBackgroundKeyBoard->IsFocused()
                || ViewModel->GetJustClickedFileNodeIndex()==-1
            )
            {
                return 0;
            }
            return 1;
        };
        JustClickedFileOrFolderHighlight->BorderColor=REditor::Get()->CurrentTheme->ItemFocusSelectedBorderColor;
    }

    auto Vertical=NewWidget<RVerticalPositionerWidget>(InParent);
    Vertical->Anchor.Fill(InParent);
    Vertical->Spacing=0;
    Vertical->Visible=[this](){return ViewModel->GetVisibleNodeNum()!=0;};
    Vertical->bClipSubWidgets=true;

    RVerticalPositionerWidgetWeakPtr WeakVertical=Vertical;
    auto CreateItem=[this,WeakVertical,WeakBackgroundKeyBoard](int64_t Index)
    {
        auto ListItemWidget=NewWidget<RMouseWidget>(WeakVertical);
        ListItemWidget->Anchor.HorizontalFill(WeakVertical);
        ListItemWidget->Height= ViewModel->LineHeight;
        ListItemWidget->OnClicked.BindLambda([this,Index,WeakBackgroundKeyBoard](const SMouseButtonEvent& InEvent)
        {
            WeakBackgroundKeyBoard->Focus();

            if(InEvent.GetButton()!=EMouseButton::Right)
            {
                ViewModel->OnNodeClicked(Index);
            }
            else
            {
                ViewModel->OnNodeRightMouseButtonClicked(Index);
            }
            return true;
        });
        ListItemWidget->OnEntered.BindLambda([this,Index]()
        {
            ViewModel->SetHoveredNodeIndex(Index);
        });
        ListItemWidget->OnExited.BindLambda([this]()
        {
            ViewModel->SetHoveredNodeIndex(-1);
        });

        auto Icon=NewWidget<RImageWidget>(ListItemWidget);
        Icon->Width=ViewModel->IconSize;
        Icon->Height=ViewModel->IconSize;
        Icon->Anchor.VerticalCenterReference=ListItemWidget;
        Icon->Anchor.LeftReference=ListItemWidget;
        Icon->Anchor.LeftOffset=[this,Index](){return ViewModel->GetLineOffset(Index);};
        Icon->Image=[this,Index](){return ViewModel->GetLineIcon(Index);};

        auto Text=NewWidget<RTextWidget>(ListItemWidget);
        Text->Anchor.LeftReference=Icon;
        Text->Anchor.LeftReferenceEdge=EHorizontalWidgetEdge::Right;
        Text->Anchor.RightReference=ListItemWidget;
        Text->Anchor.VerticalCenterReference=ListItemWidget;
        Text->Text=[this,Index](){return ViewModel->GetVisibleNodeName(Index);};
    };

    for(int i=0;i<ViewModel->GetVisibleNodeNum();i++)
    {
        CreateItem(i);
    }



    
    ViewModel->OnVisibleListSizeChanged.Bind([this,WeakVertical,CreateItem](){
        int64_t Num=ViewModel->GetVisibleNodeNum();
        int64_t OldNum=WeakVertical->GetSubWidgetNum();
        if(Num>OldNum)
        {
            for(int64_t i=OldNum;i<Num;i++)
            {
                CreateItem(i);
            }
        }
        else if(Num<OldNum)
        {
            //remove the extra widgets
            for(int64_t i=Num;i<OldNum;i++)
            {
                WeakVertical->RemoveSubWidgetAt(Num);
            }

        }
    });

    HorverBackground->Anchor.VerticalCenterReference=
    [this,WeakVertical]() ->RWidgetPtr
    {
        int64_t Index=ViewModel->GetHoveredNodeIndex();
        if(Index==-1 || Index>= WeakVertical->GetSubWidgetNum())
        {
            return nullptr;
        }
        return WeakVertical->GetSubWidget(Index);
    };

    FocusedFileOrFolderHighlight->Anchor.VerticalCenterReference=
    [this,WeakVertical]() ->RWidgetPtr
    {
        int64_t Index=ViewModel->GetFocusedNodeIndex();
        if(Index==-1)
        {
            return nullptr;
        }
        return WeakVertical->GetSubWidget(Index);
    };

    JustClickedFileOrFolderHighlight->Anchor.VerticalCenterReference=
    [this,WeakVertical]() ->RWidgetPtr
    {
        int64_t Index=ViewModel->GetJustClickedFileNodeIndex();
        if(Index==-1)
        {
            return nullptr;
        }
        return WeakVertical->GetSubWidget(Index);
    };

    //widget to edit the file name
    auto EditingNameBackground=NewWidget<RRectangleWidget>(InParent);
    EditingNameBackground->FillColor= 
        REditor::Get()->CurrentTheme->BackgroundColor;
    EditingNameBackground->BorderSize=1;
    EditingNameBackground->BorderColor=[this]()
    {
        if(!ViewModel->HasEditingNameError())
        {
            return REditor::Get()->CurrentTheme->ItemFocusSelectedBorderColor;
        }
        else
        {
            return REditor::Get()->CurrentTheme->ItemFocusSelectedBorderColorError;
        }
    };
    EditingNameBackground->Visible=[this](){return ViewModel->GetEditingFileNodeIndex()!=-1;};
    EditingNameBackground->Height=ViewModel->LineHeight;
    EditingNameBackground->Anchor.LeftReference=InParent;
    EditingNameBackground->Anchor.LeftOffset=[this]()->float
        {
            int64_t Index=ViewModel->GetEditingFileNodeIndex();
            if(Index==-1)
            {
                //is not visible
                return 0;
            }
            float Offset=ViewModel->IconSize;
            Offset+=ViewModel->GetLineOffset(Index);
            return Offset;
        };
    EditingNameBackground->Anchor.RightReference=InParent;
    EditingNameBackground->Y=[this]()->float
    {
        int64_t Index=ViewModel->GetEditingFileNodeIndex();
        if(Index==-1)
        {
            return 0;
        }
        return ViewModel->LineHeight*Index;
    };

    auto NameEditError=NewWidget<RRectangleWidget>(EditingNameBackground);
    NameEditError->FillColor=REditor::Get()->CurrentTheme->ItemSelectColorError;
    NameEditError->BorderSize=1;
    NameEditError->BorderColor=REditor::Get()->CurrentTheme->ItemFocusSelectedBorderColorError;
    NameEditError->Visible=[this](){return ViewModel->HasEditingNameError();};
    NameEditError->Anchor.HorizontalFill(EditingNameBackground);
    NameEditError->Height=ViewModel->LineHeight;
    NameEditError->Anchor.TopReference=EditingNameBackground;
    NameEditError->Anchor.TopReferenceEdge=EVerticalWidgetEdge::Bottom;
    NameEditError->bClipSubWidgets=true;

    auto NameEditErrorText=NewWidget<RTextWidget>(NameEditError);
    NameEditErrorText->Anchor.VerticalCenterReference=NameEditError;
    NameEditErrorText->Anchor.LeftReference=NameEditError;
    NameEditErrorText->Anchor.LeftOffset=5;
    NameEditErrorText->Text=[this](){return ViewModel->GetEditingNameError();};

    NameEditView->CreateWidget(EditingNameBackground);

}

void REditorFolderAbilityView::BindViewModel(TSharedObjectPtr<REditorAbilityViewModel> InViewModel)
{
    Super::BindViewModel(InViewModel);
    ViewModel=InViewModel;

    
    NameEditView=NewObject<REditorEditableTextView>(this);
    NameEditView->BindViewModel(ViewModel->GetNameEditViewModel());
}

void REditorFolderAbilityView::FillOperations(TSharedObjectPtr<RWidget> InTitleBar)
{
    auto ButtonBar=NewWidget<RHorizontalPositionerWidget>(InTitleBar);
    ButtonBar->Anchor.VerticalCenterReference=InTitleBar;
    ButtonBar->Anchor.RightReference=InTitleBar;
    ButtonBar->Spacing=ViewModel->OperationInterval;
    ButtonBar->Height=ViewModel->OperationButtonSize;

    ButtonBar->Width= 5* ViewModel->OperationButtonSize +4 * ViewModel->OperationInterval;

    auto NewAssetFileButton=WHE::CreateImageButton(
        ViewModel->NewAssetFileIcon
        ,CString(U"新建资产文件")
        ,[this](){
            ViewModel->CreateAssetFile();
        }
        ,ButtonBar
        ,ViewModel->OperationButtonSize
        ,ViewModel->OperationButtonImageSize
    );
    NewAssetFileButton->Anchor.VerticalFill(ButtonBar);
    NewAssetFileButton->Width=ViewModel->OperationButtonSize;

    auto NewFileButton=WHE::CreateImageButton(
        ViewModel->NewFileIcon
        ,CString(U"新建文件")
        ,[this](){
            ViewModel->CreateFile();
        }
        ,ButtonBar
        ,ViewModel->OperationButtonSize
        ,ViewModel->OperationButtonImageSize
    );
    NewFileButton->Anchor.VerticalFill(ButtonBar);
    NewFileButton->Width=ViewModel->OperationButtonSize;

    auto NewFolderButton=WHE::CreateImageButton(
        ViewModel->NewFolderIcon
        ,CString(U"新建文件夹")
        ,[this](){
            ViewModel->CreateFolder();
        }
        ,ButtonBar
        ,ViewModel->OperationButtonSize
        ,ViewModel->OperationButtonImageSize
    );
    NewFolderButton->Anchor.VerticalFill(ButtonBar);
    NewFolderButton->Width=ViewModel->OperationButtonSize;

    auto RefreshButton=WHE::CreateImageButton(
        ViewModel->RefreshIcon
        ,CString(U"刷新资源管理器")
        ,[this](){
            ViewModel->Refresh();
        }
        ,ButtonBar
        ,ViewModel->OperationButtonSize
        ,ViewModel->OperationButtonImageSize
    );
    RefreshButton->Anchor.VerticalFill(ButtonBar);
    RefreshButton->Width=ViewModel->OperationButtonSize;

    auto CloseAllFileButton=WHE::CreateImageButton(
        ViewModel->CloseAllFoldersIcon
        ,CString(U"折叠所有文件夹")
        ,[this](){
            ViewModel->CloseAllFolders();
        }
        ,ButtonBar
        ,ViewModel->OperationButtonSize
        ,ViewModel->OperationButtonImageSize
    );
    CloseAllFileButton->Anchor.VerticalFill(ButtonBar);
    CloseAllFileButton->Width=ViewModel->OperationButtonSize;

}
